package file

import (
	"archive/zip"
	"errors"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"io"
	"os"
	"strings"
)

// PathExists 判断路径是否存在
func PathExists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	//判断是不是不存在的错误
	if os.IsNotExist(err) {
		//如果返回的错误类型使用os.isNotExist()判断为true，说明文件或者文件夹不存在
		return false
	}
	//如果有错误了，但是不是不存在的错误直接panic
	panic(err)
}

// MkdirAll 创建所有文件,同命令 mkdir -p
func MkdirAll(path string) {
	err := os.MkdirAll(path, os.ModePerm)
	if err != nil {
		panic(err)
	}
}

// GetFileExt 获取文件的拓展名,比如 xxx.jpg
func GetFileExt(fileName string) string {
	lastIndex := strings.LastIndex(fileName, ".")
	if lastIndex == -1 {
		return ""
	}
	return fileName[lastIndex+1:]
}

// GetFileNameNoExt 只获取文件名,比如 xxx
func GetFileNameNoExt(fileName string) string {
	lastIndex := strings.LastIndex(fileName, ".")
	if lastIndex == -1 {
		return fileName
	}
	return fileName[0:lastIndex]
}

// ZipDir 文件打包为zip
func ZipDir(dir, outPath, outName string) error {
	if len(outPath) == 0 {
		outPath = dir + "_zip"
		if !PathExists(outPath) {
			MkdirAll(outPath)
		}
	}

	stat, err := os.Stat(dir)
	if err != nil {
		logx.Errorf("Stat dir error：%v", err)
		return err
	}
	if !stat.IsDir() {
		return errors.New(dir + " 不是一个文件夹")
	}

	// 第一步，创建 zip 文件
	zipFileFullPath := fmt.Sprintf("%s%c%s", outPath, os.PathSeparator, outName)
	logx.Infof("创建空的zip文件：%s", zipFileFullPath)
	zipFile, err := os.Create(zipFileFullPath)
	if err != nil {
		logx.Errorf("创建空的zip文件失败：%v", err)
		return err
	}
	defer zipFile.Close()

	// 使用 zip.NewWriter() 函数创建一个新的 *Writer 对象，用于将待压缩的文件写入到 zip 文件。
	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	// 向 zip 文件中添加当前文件夹中的所有文件
	readDirs, err := os.ReadDir(dir)
	if err != nil {
		return err
	}

	for _, entry := range readDirs {
		if entry.IsDir() {
			continue
		}

		err := func() error {
			entryWriter, err := zipWriter.Create(entry.Name())
			if err != nil {
				return err
			}
			// 打开待压缩的文件
			entryPath := fmt.Sprintf("%s%c%s", dir, os.PathSeparator, entry.Name())
			logx.Infof("开始压缩文件：%s", entryPath)
			entryFile, err := os.Open(entryPath)
			if err != nil {
				return err
			}
			defer entryFile.Close()
			// 写文件
			if _, err := io.Copy(entryWriter, entryFile); err != nil {
				return err
			}
			return nil
		}()
		if err != nil {
			return err
		}
	}

	return nil
}
